import { Tabs } from 'nextra/components'
import { Callout, Sandpack } from '@/components'

# ErrorBoundary

this component can handle any errors in children.

## Comparison

`@suspensive/react`'s `<ErrorBoundary/>` provides a declarative, feature-rich alternative to React's class-based error boundaries and popular error boundary libraries like `react-error-boundary` and `@sentry/react`.

| Feature                                  | @suspensive/react | react-error-boundary   | @sentry/react          | React Class Component  |
| ---------------------------------------- | ----------------- | ---------------------- | ---------------------- | ---------------------- |
| Basic error catching                     | ✅                | ✅                     | ✅                     | ✅                     |
| Fallback UI with error & reset           | ✅                | ✅                     | ✅                     | ⚠️ (Manual)            |
| Reset with resetKeys                     | ✅                | ✅                     | ❌                     | ⚠️ (Manual)            |
| onReset callback                         | ✅                | ✅                     | ✅                     | ⚠️ (Manual)            |
| onError callback                         | ✅                | ✅                     | ✅                     | ✅ (componentDidCatch) |
| Conditional error catching (shouldCatch) | ✅                | ❌                     | ❌                     | ⚠️ (Manual)            |
| Fallback error handling                  | ✅ (To parent)    | ❌ (Recursive)         | ❌ (Recursive)         | ⚠️ (Manual)            |
| useErrorBoundary hook                    | ✅                | ✅                     | ❌                     | ❌                     |
| useErrorBoundaryFallbackProps hook       | ✅                | ❌                     | ❌                     | ❌                     |
| ErrorBoundaryGroup                       | ✅                | ❌                     | ❌                     | ❌                     |
| HOC support                              | ✅ (with)         | ✅ (withErrorBoundary) | ✅ (withErrorBoundary) | ❌                     |
| TypeScript error type inference          | ✅ (Advanced)     | ✅ (Basic)             | ✅ (Basic)             | ⚠️ (Manual)            |
| Declarative API                          | ✅                | ✅                     | ✅                     | ❌                     |
| Automatic error reporting                | ❌                | ❌                     | ✅ (To Sentry)         | ❌                     |

<Tabs items={['@suspensive/react', 'react-error-boundary', '@sentry/react', 'React Class']}>
<Tabs.Tab>

```tsx
import { ErrorBoundary } from '@suspensive/react'

const SuspensiveExample = () => (
  <ErrorBoundary
    fallback={({ error, reset }) => (
      <div>
        <button onClick={reset}>Reset</button>
        {error.message}
      </div>
    )}
  >
    <YourComponent />
  </ErrorBoundary>
)
```

</Tabs.Tab>
<Tabs.Tab>

```tsx
import { ErrorBoundary } from 'react-error-boundary'

const ReactErrorBoundaryExample = () => (
  <ErrorBoundary
    fallbackRender={({ error, resetErrorBoundary }) => (
      <div>
        <button onClick={resetErrorBoundary}>Reset</button>
        {error.message}
      </div>
    )}
  >
    <YourComponent />
  </ErrorBoundary>
)
```

</Tabs.Tab>
<Tabs.Tab>

```tsx
import { ErrorBoundary } from '@sentry/react'

const SentryExample = () => (
  <ErrorBoundary
    fallback={({ error, resetError }) => (
      <div>
        <button onClick={resetError}>Reset</button>
        {error.message}
      </div>
    )}
  >
    <YourComponent />
  </ErrorBoundary>
)
```

</Tabs.Tab>
<Tabs.Tab>

```tsx
import { Component, ReactNode } from 'react'

class ErrorBoundary extends Component<
  { children: ReactNode; fallback: (error: Error) => ReactNode },
  { hasError: boolean; error: Error | null }
> {
  constructor(props) {
    super(props)
    this.state = { hasError: false, error: null }
  }

  static getDerivedStateFromError(error: Error) {
    return { hasError: true, error }
  }

  componentDidCatch(error: Error, errorInfo: ErrorInfo) {
    console.error('Error caught:', error, errorInfo)
  }

  render() {
    if (this.state.hasError) {
      return this.props.fallback(this.state.error!)
    }
    return this.props.children
  }
}

// Usage
const ReactClassExample = () => (
  <ErrorBoundary
    fallback={(error) => (
      <div>
        <button onClick={() => window.location.reload()}>Reset</button>
        {error.message}
      </div>
    )}
  >
    <YourComponent />
  </ErrorBoundary>
)
```

</Tabs.Tab>
</Tabs>

### Key Advantages of @suspensive/react

1. **Advanced Error Filtering with shouldCatch**: Unlike other solutions, `@suspensive/react` allows you to conditionally catch specific errors using boolean, ErrorConstructor, or callback matchers. This enables sophisticated error handling strategies where parent and child ErrorBoundaries can handle different error types.

2. **Proper Fallback Error Handling**: Unlike `react-error-boundary`, errors thrown in fallback components are passed to the parent ErrorBoundary instead of being caught recursively by the same boundary. This prevents infinite fallback loops and provides more predictable error handling behavior. [Learn more](/docs/react/migration/migrate-to-v3#now-thrown-error-in-errorboundary-fallback-will-be-passed-to-parent-1409)

3. **useErrorBoundaryFallbackProps**: Eliminates prop drilling in fallback components by providing direct access to `error` and `reset` through a hook, making deeply nested fallback UIs much cleaner.

4. **ErrorBoundaryGroup**: Manage and reset multiple ErrorBoundaries together, perfect for complex UIs with multiple error boundaries that need coordinated reset behavior.

5. **Better TypeScript Support**: Advanced type inference for error types based on shouldCatch configuration, providing better autocomplete and type safety.

6. **No Class Components Required**: Unlike native React error boundaries, you can use a fully declarative, function component-based approach without writing class components.

### Migration Guide

<Tabs items={['From react-error-boundary', '@sentry/react', 'From React Class Component']}>
<Tabs.Tab>

If you're using react-error-boundary, migrating to `@suspensive/react` is straightforward:

```tsx
// react-error-boundary
import { ErrorBoundary } from 'react-error-boundary'

const ReactErrorBoundaryExample = () => (
  <ErrorBoundary
    fallbackRender={({ error, resetErrorBoundary }) => (
      <div>
        <button onClick={resetErrorBoundary}>Reset</button>
        {error.message}
      </div>
    )}
    onReset={() => console.log('reset')}
  >
    <YourComponent />
  </ErrorBoundary>
)

// @suspensive/react - same functionality
import { ErrorBoundary } from '@suspensive/react'

const SuspensiveExample = () => (
  <ErrorBoundary
    fallback={({ error, reset }) => (
      <div>
        <button onClick={reset}>Reset</button>
        {error.message}
      </div>
    )}
    onReset={() => console.log('reset')}
  >
    <YourComponent />
  </ErrorBoundary>
)
```

Main API differences:

- `fallback`, `fallbackRender`, `FallbackComponent` → `fallback`
- `resetErrorBoundary` → `reset` (in fallback props)

</Tabs.Tab>
<Tabs.Tab>

If you're using `@sentry/react`, migrating to `@suspensive/react` is straightforward:

```tsx
// @sentry/react
import * as Sentry from '@sentry/react'

const SentryExample = () => (
  <Sentry.ErrorBoundary
    fallback={({ error, resetError }) => (
      <div>
        <button onClick={resetError}>Reset</button>
        {error.message}
      </div>
    )}
    onError={(error, componentStack, eventId) => {
      // Error automatically sent to Sentry
      console.log('Error caught:', eventId)
    }}
  >
    <YourComponent />
  </Sentry.ErrorBoundary>
)

// @suspensive/react - with manual Sentry integration
import { ErrorBoundary } from '@suspensive/react'
import * as Sentry from '@sentry/react'

const SuspensiveExample = () => (
  <ErrorBoundary
    fallback={({ error, reset }) => (
      <div>
        <button onClick={reset}>Reset</button>
        {error.message}
      </div>
    )}
    onError={(error, errorInfo) => {
      const eventId = Sentry.captureReactException(error, errorInfo)
      console.log('Error caught:', eventId)
    }}
  >
    <YourComponent />
  </ErrorBoundary>
)
```

Main differences:

- `@sentry/react` automatically reports errors to Sentry
- `@suspensive/react` provides more flexible error handling with `shouldCatch`
- `resetError` → `reset` (in fallback props)
- Manual Sentry integration gives you more control over what gets reported

</Tabs.Tab>
<Tabs.Tab>

If you're using React class components for error boundaries, `@suspensive/react` provides a much simpler declarative API:

```tsx
// React Class Component
class ErrorBoundary extends Component {
  state = { hasError: false, error: null }

  static getDerivedStateFromError(error) {
    return { hasError: true, error }
  }

  componentDidCatch(error, errorInfo) {
    logErrorToService(error, errorInfo)
  }

  reset = () => {
    this.setState({ hasError: false, error: null })
  }

  render() {
    if (this.state.hasError) {
      return <FallbackComponent error={this.state.error} reset={this.reset} />
    }
    return this.props.children
  }
}

// @suspensive/react - much simpler!
import { ErrorBoundary } from '@suspensive/react'

const SuspensiveExample = () => (
  <ErrorBoundary
    fallback={({ error, reset }) => (
      <FallbackComponent error={error} reset={reset} />
    )}
    onError={(error, errorInfo) => logErrorToService(error, errorInfo)}
  >
    <YourComponent />
  </ErrorBoundary>
)
```

</Tabs.Tab>
</Tabs>

---

### props.fallback

If there is any thrown error in children of `<ErrorBoundary/>`, Error will be caught and then fallback will be rendered.

```tsx /fallback/
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect } from 'react'

const Example = () => (
  <ErrorBoundary
    fallback={(props) => (
      <>
        <button onClick={props.reset}>Try again</button>
        {props.error.message}
      </>
    )}
  >
    <ErrorAfter2s />
  </ErrorBoundary>
)
```

<Sandpack>

```tsx Example.tsx active
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect } from 'react'
import { ErrorAfter2s } from './ErrorAfter2s'

export const Example = () => {
  return (
    <ErrorBoundary
      fallback={(props) => (
        <>
          <button onClick={props.reset}>Try again</button>
          {props.error.message}
        </>
      )}
    >
      <ErrorAfter2s />
    </ErrorBoundary>
  )
}
```

```tsx ErrorAfter2s.tsx
import { useState, useEffect } from 'react'

export const ErrorAfter2s = () => {
  const [asyncState, setAsyncState] = useState<
    { isError: true; error: Error } | { isError: false; error: null }
  >({
    isError: false,
    error: null,
  })

  useEffect(() => {
    setTimeout(() => {
      setAsyncState({ isError: true, error: new Error('error made by Error') })
    }, 2000)
  }, [])

  if (asyncState.isError) {
    throw asyncState.error
  }

  return <>No error</>
}
```

</Sandpack>

<Callout type='info'>

Define component as `<ErrorBoundary/>`'s fallback

#### ErrorBoundaryFallbackProps

If you want to deliver a declared component as `<ErrorBoundary/>`'s fallback, you can use the `ErrorBoundaryFallbackProps` type to declare the component easily.

```tsx /ErrorBoundaryFallbackProps/
import type { ErrorBoundaryFallbackProps } from '@suspensive/react'

const ErrorBoundaryFallback = ({
  reset,
  error,
}: ErrorBoundaryFallbackProps) => (
  <>
    <button onClick={reset}>reset</button>
    {error.message}
  </>
)

const Example = () => (
  <ErrorBoundary fallback={ErrorBoundaryFallback}>
    <ErrorAfter2s />
  </ErrorBoundary>
)
```

</Callout>

<Callout>

Use `<ErrorBoundary/>` fallback props without prop drilling

#### useErrorBoundaryFallbackProps

If component using `reset` method and `error` object is nested, prop drilling cannot be avoided.
The `useErrorBoundaryFallbackProps` allows you to access the `reset` method and `error` objects without prop drilling.

```tsx /useErrorBoundaryFallbackProps/
import { ErrorBoundary, useErrorBoundaryFallbackProps } from '@suspensive/react'

const Nested = () => {
  const { reset, error } = useErrorBoundaryFallbackProps()

  return (
    <>
      <button onClick={reset}>Try again</button>
      {error.message}
    </>
  )
}

// There's no need to pass fallback Prop here!
const ErrorBoundaryFallback = () => <Nested />

const Example = () => (
  <ErrorBoundary fallback={ErrorBoundaryFallback}>
    <Error />
  </ErrorBoundary>
)
```

</Callout>

### props.resetKeys

If you want to reset `<ErrorBoundary/>` by component where is outside of `<ErrorBoundary/>`'s fallback. Inject any resetKey in resetKeys. resetKeys work only when at least one element of array is changed. you don't need to worry about provide new array as resetKeys like how useEffect's dependency array work.

```tsx /resetKeys/
import { ErrorBoundary } from '@suspensive/react'
import { useState } from 'react'

const Example = () => {
  const [resetKey, setResetKey] = useState(0)

  return (
    <>
      <button onClick={() => setResetKey((prev) => prev + 1)}>Try again</button>
      <ErrorBoundary resetKeys={[resetKey]}>
        <ErrorAfter2s />
      </ErrorBoundary>
    </>
  )
}
```

<Sandpack>

```tsx Example.tsx active
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect } from 'react'
import { ErrorAfter2s } from './ErrorAfter2s'

export const Example = () => {
  const [resetKey, setResetKey] = useState(0)

  return (
    <>
      <button onClick={() => setResetKey((prev) => prev + 1)}>Try again</button>
      <ErrorBoundary
        resetKeys={[resetKey]}
        fallback={(props) => <>{props.error.message}</>}
      >
        <ErrorAfter2s />
      </ErrorBoundary>
    </>
  )
}
```

```tsx /ErrorAfter2s.tsx
import { useState, useEffect } from 'react'

export const ErrorAfter2s = () => {
  const [asyncState, setAsyncState] = useState<
    { isError: true; error: Error } | { isError: false; error: null }
  >({
    isError: false,
    error: null,
  })

  useEffect(() => {
    setTimeout(() => {
      setAsyncState({ isError: true, error: new Error('error made by Error') })
    }, 2000)
  }, [])

  if (asyncState.isError) {
    throw asyncState.error
  }

  return <>No error</>
}
```

</Sandpack>

### props.onReset

This is a callback that is called first when `<ErrorBoundary/>` reset. It can be used with @tanstack/react-query as follows.

```tsx /onReset/
import { ErrorBoundary } from '@suspensive/react'
import { QueryErrorResetBoundary } from '@tanstack/react-query'

const Example = () => (
  <QueryErrorResetBoundary>
    {({ reset }) => (
      <ErrorBoundary
        onReset={reset}
        fallback={(props) => (
          <>
            <button onClick={props.reset}>Try again</button>
            {props.error.message}
          </>
        )}
      >
        <Page />
      </ErrorBoundary>
    )}
  </QueryErrorResetBoundary>
)
```

<Sandpack>

```tsx Example.tsx active
import { ErrorBoundary } from '@suspensive/react'
import { QueryErrorResetBoundary } from '@tanstack/react-query'
import { Page } from './Page'

export const Example = () => (
  <QueryErrorResetBoundary>
    {({ reset }) => (
      <ErrorBoundary
        onReset={reset}
        fallback={(props) => (
          <>
            <button onClick={props.reset}>Try again</button>
            {props.error.message}
          </>
        )}
      >
        <Page />
      </ErrorBoundary>
    )}
  </QueryErrorResetBoundary>
)
```

```tsx /Page.tsx
import { useQuery } from '@tanstack/react-query'
import { fetchSomething } from './fetchSomething'

export const Page = () => {
  const { data, isLoading, error } = useQuery({
    queryKey: ['key'],
    queryFn: fetchSomething,
    useErrorBoundary: true,
    retry: false,
  })

  if (isLoading) return <>Loading...</>

  return <>{data}</>
}
```

```tsx /fetchSomething.ts
export const fetchSomething = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject({ status: 401, message: 'unauthorized' })
    }, 2000)
  })
}
```

</Sandpack>

### props.onError

This is a callback called when `<ErrorBoundary/>` catches an error.

```tsx /onError/
import { ErrorBoundary } from '@suspensive/react'

const logError = (error: Error, info: ErrorInfo) => {
  // ...
}

const Example = (
  <ErrorBoundary fallback={ErrorBoundaryFallback} onError={logError}>
    <ErrorAfter2s />
  </ErrorBoundary>
)
```

<Sandpack previewOptions={{ showConsoleButton: true, showConsole: true }}>

```tsx Example.tsx active
import { ErrorBoundary } from '@suspensive/react'
import { ErrorAfter2s } from './ErrorAfter2s'

const logError = (error: Error, info: ErrorInfo) => {
  console.log(error, info)
}

export const Example = () => {
  return (
    <ErrorBoundary
      fallback={(props) => (
        <>
          <button onClick={props.reset}>Try again</button>
          {props.error.message}
        </>
      )}
      onError={logError}
    >
      <ErrorAfter2s />
    </ErrorBoundary>
  )
}
```

```tsx /ErrorAfter2s.tsx
import { useState, useEffect } from 'react'

export const ErrorAfter2s = () => {
  const [asyncState, setAsyncState] = useState<
    { isError: true; error: Error } | { isError: false; error: null }
  >({
    isError: false,
    error: null,
  })

  useEffect(() => {
    setTimeout(() => {
      setAsyncState({ isError: true, error: new Error('error made by Error') })
    }, 2000)
  }, [])

  if (asyncState.isError) {
    throw asyncState.error
  }

  return <>No error</>
}
```

</Sandpack>

### props.shouldCatch

shouldCatch determines whether `<ErrorBoundary/>` should catch errors based on conditions.

It accepts three criteria: Boolean, ErrorConstructor, and Callback, and defaults to true.

<Tabs items={['ErrorConstructor', 'Callback', 'Boolean']}>
<Tabs.Tab>

```tsx /shouldCatch/
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect, createElement } from 'react'

export const Example = () => {
  return (
    <ErrorBoundary
      fallback={({ error }) => (
        <>Parent ErrorBoundary fallback: {error.message}</>
      )}
    >
      <ErrorBoundary
        shouldCatch={CustomError}
        fallback={({ error }) => (
          <>Child ErrorBoundary fallback: {error.message}</>
        )}
      >
        <CustomErrorAfter2s />
      </ErrorBoundary>
    </ErrorBoundary>
  )
}
```

</Tabs.Tab>
<Tabs.Tab>

```tsx /shouldCatch/
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect, createElement } from 'react'

export const Example = () => {
  return (
    <ErrorBoundary
      fallback={({ error }) => (
        <>Parent ErrorBoundary fallback: {error.message}</>
      )}
    >
      <ErrorBoundary
        shouldCatch={(error) => error instanceof CustomError}
        fallback={({ error }) => (
          <>Child ErrorBoundary fallback: {error.message}</>
        )}
      >
        <CustomErrorAfter2s />
      </ErrorBoundary>
    </ErrorBoundary>
  )
}
```

</Tabs.Tab>
<Tabs.Tab>

```tsx /shouldCatch/
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect, createElement } from 'react'

export const Example = () => {
  return (
    <ErrorBoundary
      fallback={({ error }) => (
        <>Parent ErrorBoundary fallback: {error.message}</>
      )}
    >
      <ErrorBoundary
        shouldCatch={false}
        fallback={({ error }) => (
          <>Child ErrorBoundary fallback: {error.message}</>
        )}
      >
        <CustomErrorAfter2s />
      </ErrorBoundary>
    </ErrorBoundary>
  )
}
```

</Tabs.Tab>
</Tabs>

You can also apply multiple criteria through array.

```tsx /shouldCatch/
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect, createElement } from 'react'

const Example = () => {
  return (
    <ErrorBoundary
      fallback={({ error }) => (
        <>Parent ErrorBoundary fallback: {error.message}</>
      )}
    >
      <ErrorBoundary
        shouldCatch={[
          false,
          CustomError,
          (error) => error instanceof CustomError,
        ]}
        fallback={({ error }) => (
          <>Child ErrorBoundary fallback: {error.message}</>
        )}
      >
        <CustomErrorAfter2s />
      </ErrorBoundary>
    </ErrorBoundary>
  )
}
```

<Sandpack>

```tsx Example.tsx active
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect, createElement } from 'react'

export const Example = () => {
  return (
    <ErrorBoundary
      fallback={({ error }) => (
        <>Parent ErrorBoundary fallback: {error.message}</>
      )}
    >
      <ErrorBoundary
        shouldCatch={CustomError}
        fallback={({ error }) => (
          <>Child ErrorBoundary fallback: {error.message}</>
        )}
      >
        <CustomErrorAfter2s />
      </ErrorBoundary>
    </ErrorBoundary>
  )
}

export class CustomError extends Error {
  constructor(...args: ConstructorParameters<ErrorConstructor>) {
    super(...args)
    console.error(...args)
  }
}

export const CustomErrorAfter2s = () => {
  const [asyncState, setAsyncState] = useState<
    { isError: true; error: CustomError } | { isError: false; error: null }
  >({
    isError: false,
    error: null,
  })

  useEffect(() => {
    setTimeout(() => {
      setAsyncState({
        isError: true,
        error: () => new CustomError('error made by CustomError'),
      })
    }, 2000)
  }, [])

  if (asyncState.isError) {
    throw asyncState.error()
  }

  return <>No error</>
}
```

</Sandpack>

<br />

<Sandpack>

```tsx Example.tsx active
import { ErrorBoundary } from '@suspensive/react'
import { useState, useEffect, createElement } from 'react'

export const Example = () => {
  return (
    <ErrorBoundary
      fallback={({ error }) => (
        <>Parent ErrorBoundary fallback: {error.message}</>
      )}
    >
      <ErrorBoundary
        shouldCatch={CustomError}
        fallback={({ error }) => (
          <>Child ErrorBoundary fallback: {error.message}</>
        )}
      >
        <ErrorAfter2s />
      </ErrorBoundary>
    </ErrorBoundary>
  )
}

export class CustomError extends Error {
  constructor(...args: ConstructorParameters<ErrorConstructor>) {
    super(...args)
    console.error(...args)
  }
}

export const ErrorAfter2s = () => {
  const [asyncState, setAsyncState] = useState<
    { isError: true; error: Error } | { isError: false; error: null }
  >({
    isError: false,
    error: null,
  })

  useEffect(() => {
    setTimeout(() => {
      setAsyncState({ isError: true, error: new Error('error made by Error') })
    }, 2000)
  }, [])

  if (asyncState.isError) {
    throw asyncState.error
  }

  return <>No error</>
}
```

</Sandpack>

## ErrorBoundary.with

`ErrorBoundary.with` is a higher-order component that wraps the component with `<ErrorBoundary/>`.
`ErrorBoundary.with` makes it easy to wrap a component.

```tsx /ErrorBoundary.with/
import { ErrorBoundary } from '@suspensive/react'

const Example = ErrorBoundary.with({ fallback: ErrorBoundaryFallback }, () => {
  const errorBoundary = useErrorBoundary()

  return <>...</>
})
```

## useErrorBoundary

### useErrorBoundary().setError

In children of `<ErrorBoundary/>`, we can use useErrorBoundary().setError to make `<ErrorBoundary/>` aware of the Error without throw.

```tsx /useErrorBoundary/
import { ErrorBoundary, useErrorBoundary } from '@suspensive/react'
import { useEffect } from 'react'

const Example = () => (
  <ErrorBoundary fallback={ErrorBoundaryFallback}>
    <SetErrorAfterFetch />
  </ErrorBoundary>
)

const SetErrorAfterFetch = () => {
  const errorBoundary = useErrorBoundary()

  useEffect(() => {
    fetchSomething().then(
      (response) => {},
      (error) => errorBoundary.setError(error) // instead of throw inside
    )
  }, [])

  return <>No error</>
}
```

<Sandpack>

```tsx Example.tsx active
import { ErrorBoundary, useErrorBoundary } from '@suspensive/react'
import { useEffect } from 'react'
import { ErrorBoundaryFallback } from './ErrorBoundaryFallback'
import { fetchSomething } from './fetchSomething'

export const Example = () => (
  <ErrorBoundary fallback={ErrorBoundaryFallback}>
    <SetErrorAfterFetch />
  </ErrorBoundary>
)

const SetErrorAfterFetch = () => {
  const errorBoundary = useErrorBoundary()

  useEffect(() => {
    fetchSomething().then(
      (response) => {},
      (error) => errorBoundary.setError(error) // instead of throw inside
    )
  }, [])

  return <>No error</>
}
```

```tsx /ErrorBoundaryFallback.tsx
import type { ErrorBoundaryFallbackProps } from '@suspensive/react'

export const ErrorBoundaryFallback = (props: ErrorBoundaryFallbackProps) => (
  <>
    <button onClick={props.reset}>Try again</button>
    {props.error.message}
  </>
)
```

```tsx /fetchSomething.ts
export const fetchSomething = () => {
  return new Promise((resolve, reject) => {
    setTimeout(() => {
      reject({ status: 401, message: 'unauthorized' })
    }, 2000)
  })
}
```

</Sandpack>

<Callout>

Controlling multiple `<ErrorBoundary/>`s

`<ErrorBoundary/>` is more powerful when used with `<ErrorBoundaryGroup/>`. Control multiple `<ErrorBoundary/>`s with `<ErrorBoundaryGroup/>`.  
Details are introduced in [`<ErrorBoundaryGroup/>` page](/docs/react/ErrorBoundaryGroup).

</Callout>
